package com.auto.survey.measurecontroller

import android.text.TextUtils
import android.util.Log
import com.auto.survey.activity.bluetooth.BluetoothManagerUtil
import com.auto.survey.activity.monitoring.entity.MonitoringPoint
import com.auto.survey.activity.monitoring.entity.MonitoringPointCtrlObservation
import com.auto.survey.geocom.CommandContext
import com.auto.survey.geocom.GeoCom
import com.auto.survey.geocom.GeoComCommon
import com.auto.survey.geocom.GeoComExecutCore
import com.auto.survey.geocom.GeoComHelper
import com.auto.survey.measurecontroller.entity.Face
import com.auto.survey.measurecontroller.entity.MeasureTask
import com.auto.survey.measurecontroller.entity.PointMeasureConfig
import com.auto.survey.util.Helper
import com.auto.survey.util.taskqueue.BluetoothTaskResult
import com.google.gson.Gson
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference
import kotlin.math.absoluteValue

/**
 * 核心测量流程控制器类
 * 负责管理整个测量过程，包括任务调度、仪器控制、数据采集和处理等
 *
 * @param geoComHelper 用于与测量仪器通信的GeoCom助手类
 * @param bluetoothManager 蓝牙管理工具类，用于处理蓝牙通信
 * @param listener 测量过程监听器，用于回调测量状态和结果
 */
class RefinedMeasureController(
    private val geoComHelper: GeoComHelper,
    private val bluetoothManager: BluetoothManagerUtil,
    private val uiCallback: MeasureUICallback,
    private val listener: MeasureProcessListener? = null
) {
    private val TAG = RefinedMeasureController::class.java.simpleName

    private var prismType = "-1"    //当前测量的模式

    // 协程作用域
    private val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    // 状态管理（线程安全）
    private val currentLoop = AtomicInteger(1)
    private val currentPointIndex = AtomicInteger(0)
    private val currentFace = AtomicReference(Face.LEFT)
    private val currentPointObservations = mutableListOf<MonitoringPointCtrlObservation>()
    private val observationsMutex = Mutex() // 保护观测值列表的互斥锁

    // 依赖组件
    private val statusManager = InstrumentStatusManager(listener, uiCallback)
    private val dataProcessor = MeasurementDataProcessor(
        SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()),
        listener
    )
    private val taskManager = BluetoothTaskManager(listener, this)

    // 配置与状态
    var currentTask: MeasureTask? = null
    private var pointMeasureConfigs = mapOf<String, PointMeasureConfig>()
    private var isBluetoothConnected = false

    // 协程状态管理
    private val isResumed = AtomicBoolean(false)
    private var currentContinuation: CancellableContinuation<BluetoothTaskResult>? = null
    private var bluetoothConnectionListener: ((Boolean) -> Unit)? = null
    private var geoComCallback: ((List<GeoCom>, CommandContext) -> Unit)? = null

    init {
        setupBluetoothListener()
        initGeoComCallback()
        geoComCallback?.let { callback ->
            if (!geoComHelper.isRegisterCallback(callback)) {
                geoComHelper.resultCallback(callback)
            }
        }
    }

    /**
     * 初始化蓝牙连接状态监听
     */
    private fun setupBluetoothListener() {
        if (bluetoothManager.isBluetoothConnected()) {
            isBluetoothConnected = true
            addInstrumentCheckCommands()
        }

        geoComHelper.onConnectionStateChanged { device, state ->
            val isConnected = bluetoothManager.isBluetoothConnected()
            isBluetoothConnected = isConnected

            // 通知UI连接状态变化
            mainScope.launch {
                uiCallback.onBluetoothStateChanged(isConnected)

                if (isConnected) {
                    uiCallback.onInitStatusChanged("蓝牙连接成功，正在检查仪器状态...")
                    addInstrumentCheckCommands()
                } else {
                    uiCallback.onInitStatusChanged("蓝牙已断开连接")
                }
            }

            // 触发外部监听器
            bluetoothConnectionListener?.invoke(isConnected)
        }
    }

    /**
     * 添加仪器状态检查命令到执行队列
     */
    private fun addInstrumentCheckCommands() {
        val checkCommands = listOf(
            GeoComCommon.CSV_GetInstrumentName,
            GeoComCommon.TMC_GetInclineSwitch,
            GeoComCommon.TMC_GetAngSwitch,
            GeoComCommon.TMC_GetAngle1,
            GeoComCommon.BAP_GetPrismType,
            GeoComCommon.TMC_GetEdmMode
        )
        geoComHelper.startExecution(checkCommands)
    }

    /**
     * 初始化GeoCom命令回调函数
     */
    private fun initGeoComCallback() {
        if (geoComCallback == null) {
            geoComCallback = { results, params ->
                results.forEach { result ->
                    Log.i(TAG,"name = ${result.name}, command=${result.command}, result=${result.result}")

                    when (result.name) {
                        GeoComCommon.CSV_GetInstrumentName.name -> handleInstrumentNameResult(result)
                        GeoComCommon.TMC_GetInclineSwitch.name -> handleInclineSwitchResult(result)
                        GeoComCommon.TMC_GetAngSwitch.name -> handleAngleSwitchResult(result)
                        GeoComCommon.TMC_GetAngle1.name -> handleAngleResult(result)
                        GeoComCommon.BAP_GetPrismType.name -> handlePrismTypeResult(result)
                        GeoComCommon.TMC_GetEdmMode.name -> handleEdmModeResult(result)
                        GeoComCommon.TMC_GetFace.name -> handleFaceCheckResult(result, params)
                        GeoComCommon.AUT_ChangeFace.name -> handleFaceChangeResult(result)
                        GeoComCommon.AUT_MakePositioning.name -> handlePositioningResult(result)
                        GeoComCommon.BAP_SearchTarget.name -> handleSearchTargetResult(result)
                    }
                }
            }
        }
    }

    /**
     * 处理仪器名称结果
     */
    private fun handleInstrumentNameResult(result: GeoCom) {
        val list = Helper.parseJson(result.result)
        if (list.size > 1 && !TextUtils.isEmpty(list[1])) {
            statusManager.updateInstrumentName(list[1])
        }
    }

    /**
     * 处理倾角开关结果
     */
    private fun handleInclineSwitchResult(result: GeoCom) {
        val list = Helper.parseJson(result.result)
        if (list.size > 1) {
            statusManager.updateInclineSwitch("1" == list[1])
        }
    }

    /**
     * 处理角度改正开关结果
     */
    private fun handleAngleSwitchResult(result: GeoCom) {
        val list = Helper.parseJson(result.result)
        if (list.size > 4) {
            statusManager.updateAngleCorrectionSwitches(
                incline = "1" == list[1],
                standAxis = "1" == list[2],
                collimation = "1" == list[3],
                tiltAxis = "1" == list[4]
            )
        }
    }

    /**
     * 处理倾角信息结果
     */
    private fun handleAngleResult(result: GeoCom) {
        if (result.result == "-1") {
            statusManager.updateInclineStatus(180.0, 180.0)
        } else {
            val list = Helper.parseJson(result.result)
            if (list.size > 6) {
                val crossIncline = list[5].toDouble()
                val lengthIncline = list[6].toDouble()

                val secT = Helper.radiansToSecond(crossIncline).absoluteValue
                val secL = Helper.radiansToSecond(lengthIncline).absoluteValue

                statusManager.updateInclineStatus(secT, secL)
            }
        }
    }

    /**
     * 处理棱镜类型结果
     */
    private fun handlePrismTypeResult(result: GeoCom) {
        val list = Helper.parseJson(result.result)
        if (list.size > 1) {
            statusManager.updateMirrorType(list[1])
        }
    }

    /**
     * 处理测量模式结果
     */
    private fun handleEdmModeResult(result: GeoCom) {
        val list = Helper.parseJson(result.result)
        if (list.size > 1) {
            prismType = list[1]
            statusManager.updateMeasureMode(list[1])
        }
    }

    /**
     * 处理盘位检查结果
     */
    private fun handleFaceCheckResult(result: GeoCom, params: CommandContext) {
        try {
            val list = Helper.parseJson(result.result)
            val currentFace = Face.fromCode(list[1])
            val isRightFace = params.externalParams["isRightFace"] as Boolean
            val pointCode = params.externalParams["pointCode"] as String

            val targetFace = if (isRightFace) Face.RIGHT else Face.LEFT

            Log.i(TAG, "处理盘位检查结果:currentFace=$currentFace, isRightFace=$isRightFace, pointCode=$pointCode, targetFace=$targetFace")

            if (currentFace == targetFace) {
                if (targetFace == Face.RIGHT) {
                    Log.i(TAG, "盘右盘位确认，已完成搜索定位，开始测量垂直角")
                }
                addFaceMeasurementTask(pointCode)
                return
            }

            // 需要切换盘位
            val switchContext = CommandContext(
                externalParams = mapOf("pointCode" to pointCode)
            )
            geoComHelper.startExecution(listOf(GeoComCommon.AUT_ChangeFace), switchContext)
        } catch (e: Exception) {
            Log.e(TAG, "处理盘位检查结果失败", e)
            listener?.onError("处理盘位信息失败: ${e.message}", null)
        }
    }

    /**
     * 处理盘位切换结果
     */
    private fun handleFaceChangeResult(result: GeoCom) {
        if (result.result == "-1") {
            Log.i(TAG, "处理盘位切换结果")
            val pointCode = currentTask?.points?.getOrNull(currentPointIndex.get())?.pointCode
            listener?.onError("盘位切换失败", pointCode)
            uiCallback.onProcessLogAdded("盘位切换失败")
        } else {
            // 盘位切换成功，根据当前盘位决定后续操作
            val currentPoint = currentTask?.points?.getOrNull(currentPointIndex.get())

            if (currentPoint != null) {
                val currentFace = currentFace.get() // 获取当前盘位（已切换后的盘位）
                Log.i(TAG, "盘位切换成功，当前盘位：$currentFace，准备处理测点：${currentPoint.pointCode}")
                uiCallback.onProcessLogAdded("盘位切换成功，当前盘位：$currentFace，准备处理测点：${currentPoint.pointName}")
                if (currentFace == Face.RIGHT) {
                    // 盘右：先执行目标搜索，再测量
                    addPreciseSearchTaskForRightFace(currentPoint)
                } else {
                    // 盘左：保持原有逻辑，直接测量
                    addFaceMeasurementTask(currentPoint.pointCode)
                }
            }
        }
    }

    /**
     * 处理定位结果
     */
    private fun handlePositioningResult(result: GeoCom) {
        val currentPoint = currentTask?.points?.getOrNull(currentPointIndex.get())
        if (result.result == "-1") {
            uiCallback.onProcessLogAdded("${currentPoint?.pointName} 目标定位失败")
            listener?.onError("目标定位失败", currentPoint?.pointCode)
        } else if (currentPoint != null) {
            // 定位成功，检查当前盘位
            uiCallback.onProcessLogAdded("${currentPoint.pointName} 目标定位成功")
            val context = CommandContext(
                externalParams = mapOf(
                    "pointCode" to currentPoint.pointCode,
                    "isRightFace" to (currentFace.get() == Face.RIGHT)
                )
            )
            geoComHelper.startExecution(listOf(GeoComCommon.TMC_GetFace), context)
        }
    }

    /**
     * 处理目标搜索结果
     */
    private fun handleSearchTargetResult(result: GeoCom) {
        Log.i(TAG, "handleSearchTargetResult ### 处理目标搜索结果")
        val currentPoint = currentTask?.points?.getOrNull(currentPointIndex.get()) ?: return
        val pointCode = currentPoint.pointCode

        if (result.result == "-1") {
            listener?.onError("未找到目标 $pointCode", pointCode)
            uiCallback.onProcessLogAdded("未找到目标 ${currentPoint.pointName}, 尝试重试")
            // 尝试重试
            if (currentTask?.config?.autoRetry == true) {
                currentPoint.retryCount++
                if (currentPoint.retryCount <= currentTask?.config?.retryCount ?: 0) {
                    listener?.onRetry(pointCode, currentPoint.retryCount, currentTask?.config?.retryCount ?: 0)
                    addTargetPositioningTask(currentPoint)
                } else {
                    listener?.onError("超过最大重试次数 $pointCode", pointCode)
                    uiCallback.onProcessLogAdded("未找到目标 ${currentPoint.pointName}, 超过最大重试次数")
                    currentTask?.status = MeasureTask.TaskStatus.FAILED
                }
            }
        } else {
            // 搜索成功，继续定位
            Log.i(TAG, "handleSearchTargetResult ### 搜索成功，继续定位")
            uiCallback.onProcessLogAdded("搜索成功 ${currentPoint.pointName}, 继续定位")
            addTargetPositioningTask(currentPoint)
        }
    }

    /**
     * 启动测量任务
     */
    fun startMeasureTask(
        task: MeasureTask,
        startLoop: Int = 1,
        pointConfigs: List<PointMeasureConfig> = emptyList()
    ) {
        if (currentTask?.status == MeasureTask.TaskStatus.RUNNING) {
            listener?.onError("已有任务正在执行", null)
            uiCallback.onProcessLogAdded("已有任务正在执行")
            return
        }

        // 验证起始测回数有效性
        if (startLoop < 1 || startLoop > task.config.loopCount) {
            listener?.onError("无效的起始测回数: $startLoop", null)
            uiCallback.onProcessLogAdded("无效的起始测回数: $startLoop")
            return
        }

        task.points [0].retryCount = 0
        currentTask = task
        task.status = MeasureTask.TaskStatus.RUNNING
        currentLoop.set(startLoop)
        currentPointIndex.set(0)
        currentPointObservations.clear()
        pointMeasureConfigs = pointConfigs.associateBy { it.pointCode }

        ioScope.launch {
            startNextLoop()
        }
    }

    /**
     * 根据观测值更新MonitoringPoint对象的属性
     */
    private fun updateMonitoringPointWithObservation(
        point: MonitoringPoint,
        observation: MonitoringPointCtrlObservation,
        isLeft: Boolean
    ) {
        when (isLeft) {
            true -> {
                point.pointHz = observation.horizontalAngleL
                point.pointV = observation.verticalAngleL
                point.pointSD = observation.distanceL
            }
            false -> {
                point.pointHz = observation.horizontalAngleR
                point.pointV = observation.verticalAngleR
                point.pointSD = observation.distanceR
            }
        }
    }

    /**
     * 安全恢复协程并返回成功结果
     */
    private fun safeResumeWithSuccess(params: Map<String, Any>) {
        val res = isResumed.compareAndSet(false, true)
        Log.i(TAG, "safeResumeWithSuccess### res = $res")
        if (res) {
            if (currentContinuation == null) {
                Log.i(TAG, "safeResumeWithSuccess### currentContinuation = null")
            }
            currentContinuation?.resume(BluetoothTaskResult.Success(params)) {
                currentContinuation = null
            }
        }
    }

    /**
     * 安全恢复协程并返回失败结果
     */
    private fun safeResumeWithFailure(reason: String) {
        if (isResumed.compareAndSet(false, true)) {
            currentContinuation?.resume(BluetoothTaskResult.Failure(reason)) {
                currentContinuation = null
            }
        }
    }

    /**
     * 处理任务成功回调
     */
    internal fun handleTaskSuccess(taskId: String, params: Map<String, Any>) {
        Log.i(TAG, "handleTaskSuccess ### taskId=$taskId, params = ${Gson().toJson(params)}")
        when {
            taskId.startsWith(MeasureConstants.TASK_PREFIX_INIT) && taskManager.pendingTaskCount() == 0 -> {
                startNextLoop()
            }

            taskId.endsWith("_LEFT") -> {
                handleLeftFaceSuccess(params)
            }

            taskId.endsWith("_RIGHT") -> {
                handleRightFaceSuccess(params)
            }
        }
    }

    /**
     * 处理盘左测量成功
     */
    private fun handleLeftFaceSuccess(params: Map<String, Any>) {
        Log.i(TAG, "handleLeftFaceSuccess ### 处理盘左测量成功")
        val observation = params["observation"] as MonitoringPointCtrlObservation
        ioScope.launch {
            observationsMutex.withLock {
                currentPointObservations.add(observation)
            }
        }



        // 更新当前测点信息
        val pointIndex = currentPointIndex.get()
        Log.i(TAG, "handleLeftFaceSuccess ###  currentPointIndex = $currentPointIndex, pointIndex = ${pointIndex}")

        currentTask?.points?.getOrNull(pointIndex)?.let { point ->
            listener?.onFaceMeasured(point.pointName,observation.monitoringPointId, currentLoop.get(), pointIndex, true, observation)

            Log.i(TAG, "handleLeftFaceSuccess ### observation= ${Gson().toJson(observation)}")
            uiCallback.onProcessLogAdded("${point.pointName}  盘左测量成功。 盘左水平角观测值（弧度）：${observation.horizontalAngleL}， " +
                    "盘左垂直角观测值（弧度）：${observation.verticalAngleL}, 盘左斜距观测值（米）:${observation.distanceL}")
            point.collected = true
            point.updateTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
            point.pointHz = observation.horizontalAngleL
            point.pointV = observation.verticalAngleL
            point.pointSD = observation.distanceL

            // 检查是否需要测量盘右
            val pointConfig = pointMeasureConfigs[point.pointCode]
            val needRightFace = pointConfig?.includeRightFace != false &&
                    currentTask?.config?.needLeftRight == true

            Log.i(TAG, "handleLeftFaceSuccess ### needRightFace = $needRightFace")
            if (needRightFace) {
                currentFace.set(Face.RIGHT)
                addFaceMeasurementTask(point.pointCode)
            } else {
                processPointMeasurements()
            }
        }
    }

    /**
     * 处理盘右测量成功
     */
    private fun handleRightFaceSuccess(params: Map<String, Any>) {
        Log.i(TAG, "handleRightFaceSuccess ### 处理盘右测量成功")
        val observation = params["observation"] as MonitoringPointCtrlObservation
        ioScope.launch {
            observationsMutex.withLock {
                currentPointObservations.add(observation)
            }
        }



        Log.i(TAG, "handleRightFaceSuccess ### observation= ${Gson().toJson(observation)}")
        // 更新当前测点信息
        val pointIndex = currentPointIndex.get()
        currentTask?.points?.getOrNull(pointIndex)?.let { point ->
            listener?.onFaceMeasured(point.pointName, observation.monitoringPointId,currentLoop.get(),  pointIndex, false, observation)
            uiCallback.onProcessLogAdded("${point.pointName}  盘右测量成功。 盘右水平角观测值（弧度）：${observation.horizontalAngleR}， " +
                    "盘右垂直角观测值（弧度）：${observation.verticalAngleR}, 盘右斜距观测值（米）:${observation.distanceR}")

            point.pointHz = observation.horizontalAngleR
            point.pointV = observation.verticalAngleR
            point.pointSD = observation.distanceR
            processPointMeasurements()
        }
    }

    /**
     * 开始下一测回的测量
     */
    private fun startNextLoop() {
        val task = currentTask ?: return
        val loop = currentLoop.get()

        if (loop > task.config.loopCount) {
            calculateCloseError()
            return
        }

        listener?.onLoopStarted(loop, task.config.loopCount)
        uiCallback.onProcessLogAdded("开始第${loop}/${task.config.loopCount}测回的测量")
        currentPointIndex.set(0)
        startProcessNextPoint () // 调用新的入口方法

    }

    private fun startProcessNextPoint() {
        ioScope.launch {
            doProcessNextPoint()
        }
    }

    private suspend fun doProcessNextPoint () = withContext (Dispatchers.IO) {
        val task = currentTask ?: return@withContext
        var pointIndex = currentPointIndex.get ()
        // 循环处理测点，替代递归调用
        while (pointIndex < task.points.size) {
            val currentPoint = task.points [pointIndex]

            val pointConfig = pointMeasureConfigs [currentPoint.pointCode]
            // 检查是否需要跳过当前测回
            if (pointConfig?.skipLoops?.contains (currentLoop.get ()) == true) {
                Log.i (TAG, " 跳过测点 ${currentPoint.pointCode} 的第 ${currentLoop.get ()} 测回 ")
                currentPointIndex.incrementAndGet ()
                pointIndex = currentPointIndex.get () // 更新索引
                continue // 继续处理下一个测点
            }
            // 处理当前测点
            listener?.onPointProcessing (currentPoint.pointCode, currentLoop.get ())
            // 根据配置决定起始盘位
            currentFace.set(
                if (pointConfig?.includeLeftFace == false) Face.RIGHT
                else Face.LEFT
            )
            // 清空当前测点观测值
            observationsMutex.withLock {
                currentPointObservations.clear ()
            }

            // 1. 基于学习数据进行粗定位 - 显式指定lambda类型
            taskManager.addRoughPositionTask(currentPoint, currentLoop.get()) {
                val roughPositionResult: BluetoothTaskResult = executeGeoComCommand(
                    GeoComCommon.AUT_MakePositioning(
                        dsrchHz = currentPoint.pointHz?.toString() ?: MeasureConstants.DEFAULT_SEARCH_HZ.toString(),
                        dsrchV = currentPoint.pointV?.toString() ?: MeasureConstants.DEFAULT_SEARCH_HZ.toString()
                    )
                )

                when (roughPositionResult) {
                    is BluetoothTaskResult.Success -> {
                        Log.i(TAG, "测点 ${currentPoint.pointCode} 粗定位完成")
                        uiCallback.onProcessLogAdded("测点 ${currentPoint.pointName} 粗定位完成")
                        BluetoothTaskResult.Success(emptyMap())
                    }
                    is BluetoothTaskResult.Failure -> {
                        uiCallback.onProcessLogAdded("测点 ${currentPoint.pointName} 粗定位失败")
                        if (currentPoint.retryCount < task.config.retryCount) {
                            currentPoint.retryCount++
                            listener?.onRetry(
                                currentPoint.pointCode,
                                currentPoint.retryCount,
                                task.config.retryCount
                            )
                            roughPositionResult
                        } else {
                            BluetoothTaskResult.Failure(
                                "测点 ${currentPoint.pointCode} 粗定位失败，已达最大重试次数"
                            )
                        }
                    }
                }
            }

            // 2. 精细搜索 - 显式指定lambda类型
            taskManager.addPreciseSearchTask(currentPoint, currentLoop.get()) {
                val searchResult: BluetoothTaskResult = executeGeoComCommand(GeoComCommon.BAP_SearchTarget)
                when (searchResult) {
                    is BluetoothTaskResult.Success -> {
                        Log.i(TAG, "测点: ${currentPoint.pointName}, 编号：${currentPoint.pointCode} 精细搜索完成")
                        uiCallback.onProcessLogAdded("测点 ${currentPoint.pointName} 精细搜索完成")
                        BluetoothTaskResult.Success(emptyMap())
                    }
                    is BluetoothTaskResult.Failure -> {
                        uiCallback.onProcessLogAdded("测点 ${currentPoint.pointName} 搜索目标失")
                        BluetoothTaskResult.Failure(
                            "测点 ${currentPoint.pointCode} 搜索目标失败: ${searchResult.reason}"
                        )
                    }
                }
            }
            // 3. 确认目标定位 - 显式指定lambda类型
            taskManager.addConfirmPositionTask(currentPoint, currentLoop.get()) {
                val confirmResult: BluetoothTaskResult = executeGeoComCommand(
                    GeoComCommon.AUT_MakePositioning(
                        dsrchHz = currentPoint.pointHz.toString(),
                        dsrchV = currentPoint.pointV.toString()
                    )
                )

                when (confirmResult) {
                    is BluetoothTaskResult.Success -> {
                        Log.i(TAG, "定位成功后检查盘位")
                        // 定位成功后检查盘位，准备测量
                        val context = CommandContext(
                            externalParams = mapOf(
                                "pointCode" to currentPoint.pointCode,
                                "isRightFace" to (currentFace.get() == Face.RIGHT)
                            )
                        )
                        geoComHelper.startExecution(listOf(GeoComCommon.TMC_GetFace), context)
                        BluetoothTaskResult.Success(emptyMap())
                    }
                    is BluetoothTaskResult.Failure -> {
                        uiCallback.onProcessLogAdded("测点 ${currentPoint.pointName} 精确定位失败")
                        BluetoothTaskResult.Failure(
                            "测点 ${currentPoint.pointCode} 精确定位失败: ${confirmResult.reason}"
                        )
                    }
                }
            }
            // 当前测点的任务已添加到队列，退出循环（等待任务完成后再处理下一个）
            break
        }
        // 所有测点处理完成，进入下一测回
        if (pointIndex>= task.points.size) {
            currentLoop.incrementAndGet ()
            delay (task.config.loopInterval * 1000L)
            startNextLoop ()
        }
    }



    /**
     * 添加目标定位任务到队列
     */
    private fun addTargetPositioningTask(point: MonitoringPoint) {
        Log.i(TAG, "addTargetPositioningTask ### 添加目标定位任务到队列")
        taskManager.addPositioningTask(point, currentLoop.get()) {
            val positioningGeoCom = GeoComCommon.AUT_MakePositioning(
                dsrchHz = point.pointHz?.toString() ?: MeasureConstants.DEFAULT_SEARCH_HZ.toString(),
                dsrchV = point.pointV?.toString() ?: MeasureConstants.DEFAULT_SEARCH_HZ.toString()
            )

            val result = executeGeoComCommand(positioningGeoCom)
            if (result is BluetoothTaskResult.Failure) {
                return@addPositioningTask result
            }

            delay(MeasureConstants.DELAY_AFTER_POSITIONING)
            val context = CommandContext(
                externalParams = mapOf(
                    "pointCode" to point.pointCode,
                    "isRightFace" to (currentFace.get() == Face.RIGHT)
                )
            )
            geoComHelper.startExecution(listOf(GeoComCommon.TMC_GetFace), context)

            BluetoothTaskResult.Success(emptyMap())
        }
    }

    /**
     * 盘右切换后执行目标搜索（精细搜索）
     */
    private fun addPreciseSearchTaskForRightFace(point: MonitoringPoint) {
        Log.i(TAG, "盘右切换后，开始搜索目标：${point.pointCode}")
        // 添加精细搜索任务（复用现有方法，确保搜索范围精准）
        taskManager.addPreciseSearchTask(point, currentLoop.get()) {
            val searchResult: BluetoothTaskResult = executeGeoComCommand(
                GeoComCommon.BAP_SearchTarget
            )
            when (searchResult) {
                is BluetoothTaskResult.Success -> {
                    Log.i(TAG, "盘右目标搜索成功：${point.pointCode}，准备定位")
                    // 搜索成功后，执行定位（确保仪器对准目标）
                    val positioningResult = executeGeoComCommand(
                        GeoComCommon.AUT_MakePositioning(
                            dsrchHz = point.pointHz?.toString() ?: MeasureConstants.DEFAULT_PRECISE_SEARCH_HZ.toString(),
                            dsrchV = point.pointV?.toString() ?: MeasureConstants.DEFAULT_PRECISE_SEARCH_HZ.toString()
                        )
                    )
                    if (positioningResult is BluetoothTaskResult.Success) {
                        Log.i(TAG, "盘右目标定位成功：${point.pointCode}，准备测量")
                        // 定位成功后，确认盘位并开始测量
                        val context = CommandContext(
                            externalParams = mapOf(
                                "pointCode" to point.pointCode,
                                "isRightFace" to true // 明确当前是盘右
                            )
                        )
                        geoComHelper.startExecution(listOf(GeoComCommon.TMC_GetFace), context)
                        BluetoothTaskResult.Success(emptyMap())
                    } else {
                        BluetoothTaskResult.Failure("盘右目标定位失败：${(positioningResult as BluetoothTaskResult.Failure).reason}")
                    }
                }
                is BluetoothTaskResult.Failure -> {
                    BluetoothTaskResult.Failure("盘右目标搜索失败：${searchResult.reason}")
                }
            }
        }
    }

    /**
     * 添加盘位测量任务到队列
     */
    private fun addFaceMeasurementTask(pointCode: String) {
        val isLeft = currentFace.get() == Face.LEFT
        val loop = currentLoop.get()
        Log.i(TAG, "添加盘位测量任务到队列:isLeft=$isLeft, loop=$loop")


        // 查找当前测点
        val currentPoint = currentTask?.points?.find { it.pointCode == pointCode } ?: return
        // 触发测量中回调
        listener?.onFaceMeasuring(currentPoint.pointName, pointCode, loop, isLeft)
        Log.i(TAG, "addFaceMeasurementTask ### 查找当前测点:currentPoint name=${currentPoint.pointName}, pointCode=${currentPoint.pointCode}")


        if (!isLeft) {
            Log.i(TAG, "执行盘位切换（盘左→盘右）")
            uiCallback.onProcessLogAdded("执行盘位切换（盘左→盘右）")
            taskManager.addFaceChangeTask(pointCode, currentLoop.get(), isLeft) {
                val changedFaceResult :BluetoothTaskResult = executeGeoComCommand(GeoComCommon.AUT_ChangeFace)
                when (changedFaceResult) {
                    is BluetoothTaskResult.Success -> {

                        Log.i(TAG, "测点: ${currentPoint.pointName}, 编号：${currentPoint.pointCode} 变更盘右")
                        val searchResult: BluetoothTaskResult = executeGeoComCommand(GeoComCommon.BAP_SearchTarget)
                        if (searchResult is BluetoothTaskResult.Success) {
                            Log.i(TAG, "测点: ${currentPoint.pointName}, 编号：${currentPoint.pointCode} （盘左→盘右） 精细搜索完成")

                            uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘右） 精细搜索完成, 执行测量...")

                            Log.i(TAG, "所有准备步骤完成，执行测量 prismType = $prismType")
                            val measureGeoCom = GeoComCommon.BAP_MeasDistanceAngle(prismType)
                            val measureResult = executeGeoComCommand(measureGeoCom)

                            when (measureResult) {
                                is BluetoothTaskResult.Success -> {
                                    uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘右） 执行测量成功")
                                    Log.i(TAG, "addFaceMeasurementTask 执行测量成功")
                                    Log.i(TAG, "measureResult  = ${Gson().toJson(measureResult)}")
                                    val observation = dataProcessor.parseObservationResult(
                                        pointCode = pointCode,
                                        resultData = measureResult.params["response"] as String,
                                        isLeft = isLeft,
                                        pointId = currentPoint.id
                                    )
                                    BluetoothTaskResult.Success(mapOf("observation" to observation))
                                }
                                is BluetoothTaskResult.Failure -> measureResult
                            }

                        } else {
                            uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘左→盘右）搜索失败")
                            BluetoothTaskResult.Failure(
                                "测点 ${currentPoint.pointCode} （盘左→盘右）搜索失败"
                            )
                        }
                    }
                    is BluetoothTaskResult.Failure -> {
                        uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘左→盘右）变更失败")
                        BluetoothTaskResult.Failure(
                            "测点 ${currentPoint.pointCode} 变更失败: ${changedFaceResult.reason}"
                        )
                    }
                }
            }
        }else{
            uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘左）开始测量...")
            taskManager.addFaceMeasurementTask(pointCode, loop, isLeft) {
                Log.i(TAG, "所有准备步骤完成，执行测量 prismType = $prismType")
                val measureGeoCom = GeoComCommon.BAP_MeasDistanceAngle(prismType)
                Log.i(TAG, "addFaceMeasurementTask 执行测量")
                val measureResult = executeGeoComCommand(measureGeoCom)

                when (measureResult) {
                    is BluetoothTaskResult.Success -> {
                        uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, （盘左） 执行测量成功")
                        Log.i(TAG, "measureResult  = ${Gson().toJson(measureResult)}")
                        val observation = dataProcessor.parseObservationResult(
                            pointCode = pointCode,
                            resultData = measureResult.params["response"] as String,
                            isLeft = isLeft,
                            pointId = currentPoint.id
                        )
                        BluetoothTaskResult.Success(mapOf("observation" to observation))
                    }
                    is BluetoothTaskResult.Failure -> measureResult
                }
            }
        }

    }

    /**
     * 处理测点测量结果
     */
    private fun processPointMeasurements() {
        val task = currentTask ?: return
        val pointIndex = currentPointIndex.get()
        val currentPoint = task.points.getOrNull(pointIndex) ?: return
        Log.i(TAG, "processPointMeasurements ### 处理测点测量结果")
        uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, 开始处理测点测量结果")
        // 保存观测值
        val observations = mutableListOf<MonitoringPointCtrlObservation>()
        ioScope.launch {
            observationsMutex.withLock {
                Log.i(TAG, "processPointMeasurements ### currentPointObservations = ${Gson().toJson(currentPointObservations)}")

                observations.addAll(currentPointObservations)
            }

            withContext(Dispatchers.Main) {
                currentPoint.observations.addAll(observations)

                // 计算2C和2D互差
                dataProcessor.calculateObservationDifferences(observations)

                // 检查观测质量

                val (isQualified, message) = dataProcessor.checkObservationQuality(
                    observations,
                    task.config
                )
                Log.i(TAG, "processPointMeasurements ### 检查观测质量 isQualified = $isQualified， message = $message")

                if (!isQualified && task.config.autoRetry) {
                    uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, 测量质量不达标， $message")
                    listener?.onRetry(
                        currentPoint.pointCode,
                        currentPoint.retryCount + 1,
                        task.config.retryCount
                    )
                    currentPoint.retryCount++

                    // 根据配置决定重试哪些盘位
                    val pointConfig = pointMeasureConfigs[currentPoint.pointCode]
                    currentFace.set(
                        if (pointConfig?.includeLeftFace == false) Face.RIGHT
                        else Face.LEFT
                    )

                    addFaceMeasurementTask(currentPoint.pointCode)
                } else if (!isQualified) {
                    uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, 测量质量不达标， $message")
                    Log.i(TAG, "processPointMeasurements ### 测量质量不达标 , pointname = ${currentPoint.pointName}, pointcode = ${currentPoint.pointCode}")
                    listener?.onError(message ?: "测量质量不达标", currentPoint.pointCode)
                    currentTask?.status = MeasureTask.TaskStatus.FAILED
                } else {
                    // 处理下一个测点
                    uiCallback.onProcessLogAdded("测点: ${currentPoint.pointName}, 测量质量达标， $message")
                    currentPointIndex.incrementAndGet()
                    startProcessNextPoint()
                }
            }
        }
    }

    /**
     * 计算闭合差
     */
    /**
     * 计算闭合差
     */
    private fun calculateCloseError() {
        val task = currentTask ?: return

        // 计算各测回平均值（修复 averageOrNull 问题）
        val pointAverages = task.points.associate { point ->
            // 提取有效观测值并计算平均值
            val validObservations = point.observations
                .mapNotNull { obs ->
                    when {
                        obs.horizontalAngleL != null && obs.horizontalAngleR != null ->
                            (obs.horizontalAngleL!! + (obs.horizontalAngleR!! + Math.PI)) / 2
                        obs.horizontalAngleL != null -> obs.horizontalAngleL
                        obs.horizontalAngleR != null -> obs.horizontalAngleR
                        else -> null
                    }
                }

            // 列表为空时返回 0.0，否则计算平均值
            val hzAvg = if (validObservations.isEmpty()) 0.0 else validObservations.average()
            point.pointCode to hzAvg
        }

        // 计算闭合差
        val totalAngle = task.points.sumOf { pointAverages[it.pointCode] ?: 0.0 }
        val expectedAngle = (task.points.size - 2) * Math.PI
        val closeError = Math.abs(totalAngle - expectedAngle) * MeasureConstants.RAD_TO_SEC

        listener?.onCloseErrorCalculated(closeError, task.config.maxTotalCloseError)

        // 判断任务结果
        mainScope.launch {
            if (closeError <= task.config.maxTotalCloseError) {
                task.status = MeasureTask.TaskStatus.COMPLETED
                listener?.onTaskCompleted(task)
            } else {
                task.status = MeasureTask.TaskStatus.FAILED
                listener?.onTaskFailed(
                    task.taskId,
                    "闭合差超限: ${String.format("%.2f", closeError)} 秒，允许值: ${task.config.maxTotalCloseError} 秒"
                )
            }
        }
    }


    /**
     * 执行GeoCom命令并返回结果
     */
    private suspend fun executeGeoComCommand(geoCom: GeoCom): BluetoothTaskResult {
        return suspendCancellableCoroutine { continuation ->
            // 重置任务状态
            isResumed.set(false)
            currentContinuation = continuation

            ioScope.launch {
                try {
                    val result = geoComHelper.executeCommands(
                        listOf(GeoComExecutCore(bluetoothManager, geoCom, geoComHelper))
                    )

                    Log.i(TAG, "executeGeoComCommand ### result = $result")
                    // 处理命令结果
                    if (result.isNotEmpty() && result.first().result != "-1") {
                        Log.i(TAG, "executeGeoComCommand ### result safeResumeWithSuccess")
                        safeResumeWithSuccess(
                            mapOf("response" to (result.first().result ?: ""))
                        )
                    } else {
                        safeResumeWithFailure("命令执行失败: ${geoCom.name}")
                    }
                } catch (e: IOException) {
                    val msg = "蓝牙通信失败: ${e.message}"
                    Log.e(TAG, msg, e)
                    safeResumeWithFailure(msg)
                } catch (e: Exception) {
                    val msg = "命令执行异常: ${e.message}"
                    Log.e(TAG, msg, e)
                    safeResumeWithFailure(msg)
                }
            }

            // 处理协程取消
            continuation.invokeOnCancellation {
                if (isResumed.compareAndSet(false, true)) {
                    currentContinuation = null
                }
            }
        }
    }

    /**
     * 完成当前测量流程
     */
    internal fun completeCurrentProcess() {
        currentTask?.let {
            if (it.status == MeasureTask.TaskStatus.RUNNING) {
                it.status = MeasureTask.TaskStatus.COMPLETED
            }
        }
    }

    /**
     * 暂停测量任务
     */
    fun pause() {
        taskManager.pause()
    }

    /**
     * 恢复暂停的测量任务
     */
    fun resume() {
        taskManager.resume()
    }

    /**
     * 终止当前测量任务
     */
    fun abort() {
        taskManager.cancelAll()
        currentTask?.status = MeasureTask.TaskStatus.ABORTED
        listener?.onTaskFailed(currentTask?.taskId ?: "unknown_task", "任务已终止")
    }

    /**
     * 释放资源
     */
    fun release() {
        geoComCallback?.let {
            geoComHelper.removeResultCallback(it)
        }
        ioScope.cancel("Controller released")
        mainScope.cancel("Controller released")
        taskManager.cancelAll()
    }

    /**
     * 暴露蓝牙连接状态监听给外部
     */
    fun setBluetoothConnectionListener(listener: (Boolean) -> Unit) {
        this.bluetoothConnectionListener = listener
    }

    /**
     * 单独测量指定测点的指定盘位
     */
    fun measureSingleFace(pointCode: String, loopNo: Int, isLeft: Boolean) {
        val task = currentTask ?: run {
            listener?.onError("没有正在执行的任务", pointCode)
            return
        }

        // 查找该测点是否存在
        val point = task.points.find { it.pointCode == pointCode } ?: run {
            listener?.onError("测点 $pointCode 不存在", pointCode)
            return
        }

        // 保存当前状态，执行单点测量后恢复
        val savedLoop = currentLoop.get()
        val savedPointIndex = currentPointIndex.get()
        val savedFace = currentFace.get()

        // 执行单点测量
        currentLoop.set(loopNo)
        currentPointIndex.set(task.points.indexOf(point))
        currentFace.set(if (isLeft) Face.LEFT else Face.RIGHT)

        ioScope.launch {
            observationsMutex.withLock {
                currentPointObservations.clear()
            }
        }

        // 添加盘位测量任务
        taskManager.addSingleMeasureTask(pointCode, loopNo, isLeft) {
            // 先定位目标
            val positioningResult = executeGeoComCommand(
                GeoComCommon.AUT_MakePositioning(
                    MeasureConstants.DEFAULT_SEARCH_HZ.toString(),
                    MeasureConstants.DEFAULT_SEARCH_HZ.toString()
                )
            )

            if (positioningResult is BluetoothTaskResult.Failure) {
                // 恢复状态
                restoreMeasurementState(savedLoop, savedPointIndex, savedFace)
                return@addSingleMeasureTask positioningResult
            }

            delay(MeasureConstants.DELAY_AFTER_POSITIONING)

            // 检查并切换到目标盘位
            val faceResult = executeGeoComCommand(GeoComCommon.TMC_GetFace)
            if (faceResult is BluetoothTaskResult.Success) {
                try {
                    val list = Helper.parseJson(faceResult.params["response"] as String)
                    val currentFace = Face.fromCode(list[1])

                    if ((isLeft && currentFace != Face.LEFT) ||
                        (!isLeft && currentFace != Face.RIGHT)) {

                        val switchResult = executeGeoComCommand(GeoComCommon.AUT_ChangeFace)
                        if (switchResult is BluetoothTaskResult.Failure) {
                            restoreMeasurementState(savedLoop, savedPointIndex, savedFace)
                            return@addSingleMeasureTask switchResult
                        }
                        delay(MeasureConstants.DELAY_AFTER_SWITCH_FACE)
                    }
                } catch (e: Exception) {
                    restoreMeasurementState(savedLoop, savedPointIndex, savedFace)
                    return@addSingleMeasureTask BluetoothTaskResult.Failure(
                        "切换盘位失败: ${e.message}"
                    )
                }
            }

            // 执行测量
            val measureGeoCom = GeoComCommon.BAP_MeasDistanceAngle("2")
            val measureResult = executeGeoComCommand(measureGeoCom)

            val result = when (measureResult) {
                is BluetoothTaskResult.Success -> {
                    val observation = dataProcessor.parseObservationResult(
                        pointCode = pointCode,
                        resultData = measureResult.params["response"] as String,
                        isLeft = isLeft,
                        pointId = point.id
                    )
                    // 找到对应的测点并更新
                    val targetPoint = task.points.find { it.pointCode == pointCode }
                    targetPoint?.let {
                        updateMonitoringPointWithObservation(it, observation, isLeft)
                        it.observations.add(observation)
                        it.collected = true
                        it.updateTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
                    }
                    listener?.onFaceMeasured(targetPoint?.pointName ?: "", point.id,loopNo, 1,true, observation)
                    BluetoothTaskResult.Success(mapOf("observation" to observation))
                }
                is BluetoothTaskResult.Failure -> measureResult
            }

            // 恢复状态
            restoreMeasurementState(savedLoop, savedPointIndex, savedFace)
            result
        }
    }

    /**
     * 恢复测量状态
     */
    private fun restoreMeasurementState(savedLoop: Int, savedPointIndex: Int, savedFace: Face) {
        currentLoop.set(savedLoop)
        currentPointIndex.set(savedPointIndex)
        currentFace.set(savedFace)
    }
}
